﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace GGEditor.API
{
    public static class PluginPaths
    {
		public const char PathSeparator = '/';
		public const char PathCommandSeparator = ':';
		public const char PathPropertySeparator = '.';

    	private static readonly string PathRegexPattern =
			@"^(?<node>/$|(/[A-Z][a-zA-Z0-9]*)+)" +
			@"(:(?<command>[A-Z][a-zA-Z0-9]*)|" +
			@"\.(?<property>[A-Z][a-zA-Z0-9]*))?$";

    	private static readonly Regex PathRegex;

		static PluginPaths()
		{
			PathRegex = new Regex(PathRegexPattern);
		}

    	public static PluginPathType GetPathType(string path)
		{
			Match m = PathRegex.Match(path);

			if (!m.Success)
				return PluginPathType.InvalidPath;

			if (m.Groups["command"].Success)
				return PluginPathType.CommandPath;

			if (m.Groups["property"].Success)
				return PluginPathType.PropertyPath;

			return PluginPathType.NodePath;
		}

		public static string Join(params string[] parts)
        {
            return PathSeparator + string.Join(PathSeparator.ToString(), parts);
		}

		public static string JoinCommand(string[] parts, string command)
		{
			return Join(parts) + PathCommandSeparator + command;
		}

		public static string JoinProperty(string[] parts, string property)
		{
			return Join(parts) + PathPropertySeparator + property;
		}

		public static string[] Split(string path)
		{
			string command;
			string property;

			return Split(path, out command, out property);
		}

        public static string[] Split(string path, out string command, out string property)
        {
			string node;

			Split(path, out node, out command, out property);

			return node.Split(PathSeparator);
		}

		public static void Split(string path, out string node, out string command, out string property)
		{
			Match m = PathRegex.Match(path);

			if (!m.Success || !m.Groups["node"].Success)
				throw new PluginPathException();

			command = m.Groups["command"].Success ? m.Groups["command"].Value : null;
			property = m.Groups["property"].Success ? m.Groups["property"].Value : null;
			node = m.Groups["node"].Value;
		}

		public static string GetCommand(string path)
		{
			string node, command, property;
			Split(path, out node, out command, out property);
			return command;
		}

		public static string GetProperty(string path)
		{
			string node, command, property;
			Split(path, out node, out command, out property);
			return property;
		}

		public static string GetNodePath(string path)
		{
			string node, command, property;
			Split(path, out node, out command, out property);
			return node;
		}

        public static string GetNodeName(string path)
        {
            string[] parts = Split(path);
            return parts[parts.Length - 1];
		}

        public static string GetParentPath(string path)
        {
            string[] parts = Split(path);
            return string.Join(PathSeparator.ToString(), parts, 0, parts.Length - 1);
        }
    }

	public enum PluginPathType
	{
		InvalidPath = 0,
		NodePath,
		CommandPath,
		PropertyPath
	}

	public class PluginPathException : Exception {}
}